#pragma once

#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include "viml/value_fwd.h"

namespace viml {

// 前向声明
class DebugInfo;

/**
 * VimL虚拟机操作码
 * 
 * 指令格式：32位定长
 * | OpCode(8位) | A(8位) | B(8位) | C(8位) |
 * | OpCode(8位) | A(8位) | Bx(16位)        |
 */
enum class OpCode : uint8_t {
    // 数据移动指令
    LOAD_CONST = 0x01,      // LOAD_CONST A, Bx    R[A] = K[Bx]
    LOAD_NIL = 0x02,        // LOAD_NIL A          R[A] = nil
    LOAD_TRUE = 0x03,       // LOAD_TRUE A         R[A] = true
    LOAD_FALSE = 0x04,      // LOAD_FALSE A        R[A] = false
    MOVE = 0x05,            // MOVE A, B           R[A] = R[B]

    // 全局变量操作
    LOAD_GLOBAL = 0x10,     // LOAD_GLOBAL A, Bx   R[A] = globals[K[Bx]]
    STORE_GLOBAL = 0x11,    // STORE_GLOBAL A, Bx  globals[K[Bx]] = R[A]

    // 局部变量操作
    LOAD_LOCAL = 0x12,      // LOAD_LOCAL A, B     R[A] = locals[B]
    STORE_LOCAL = 0x13,     // STORE_LOCAL A, B    locals[B] = R[A]
    
    // 作用域变量操作
    LOAD_SCOPE = 0x14,      // LOAD_SCOPE A, ScopeId, Nidx   R[A] = scope[ScopeId][name]
    STORE_SCOPE = 0x15,     // STORE_SCOPE ScopeId, Nidx, B  scope[ScopeId][name] = R[B]

    // 算术运算指令
    ADD = 0x20,             // ADD A, B, C         R[A] = R[B] + R[C]
    SUB = 0x21,             // SUB A, B, C         R[A] = R[B] - R[C]
    MUL = 0x22,             // MUL A, B, C         R[A] = R[B] * R[C]
    DIV = 0x23,             // DIV A, B, C         R[A] = R[B] / R[C]
    MOD = 0x24,             // MOD A, B, C         R[A] = R[B] % R[C]
    NEG = 0x25,             // NEG A, B            R[A] = -R[B]

    // 比较运算指令
    EQ = 0x30,              // EQ A, B, C          R[A] = R[B] == R[C]
    NE = 0x31,              // NE A, B, C          R[A] = R[B] != R[C]
    LT = 0x32,              // LT A, B, C          R[A] = R[B] < R[C]
    LE = 0x33,              // LE A, B, C          R[A] = R[B] <= R[C]
    GT = 0x34,              // GT A, B, C          R[A] = R[B] > R[C]
    GE = 0x35,              // GE A, B, C          R[A] = R[B] >= R[C]

    // 逻辑运算指令
    AND = 0x36,             // AND A, B, C         R[A] = R[B] && R[C]
    OR = 0x37,              // OR A, B, C          R[A] = R[B] || R[C]
    NOT = 0x38,             // NOT A, B            R[A] = !R[B]

    // 控制流指令
    JMP = 0x40,             // JMP Bx              pc += Bx
    JMP_IF_TRUE = 0x41,     // JMP_IF_TRUE A, Bx   if R[A] then pc += Bx
    JMP_IF_FALSE = 0x42,    // JMP_IF_FALSE A, Bx  if !R[A] then pc += Bx
    
    // 迭代指令
    ITER_INIT = 0x43,       // ITER_INIT A, B      R[A] = iterator(R[B]), R[A+1] = 0 (index)
    ITER_NEXT = 0x44,       // ITER_NEXT A, Bx     if R[A].hasNext() { R[A+2] = next(), pc += Bx } else continue

    // 函数调用指令
    CALL = 0x50,            // CALL A, B, C        R[A..A+C-1] = call(R[B], R[A+1..A+B])
    RETURN_OP = 0x51,       // RETURN A, B         return R[A..A+B-1]
    FUNC_DEF = 0x52,        // FUNC_DEF A, Bx      define function at index A, jump over function body by Bx

    // 数据结构操作
    NEW_LIST = 0x60,        // NEW_LIST A, B       R[A] = new list(capacity=B)
    NEW_DICT = 0x61,        // NEW_DICT A          R[A] = new dict()
    GET_INDEX = 0x62,       // GET_INDEX A, B, C   R[A] = R[B][R[C]]
    SET_INDEX = 0x63,       // SET_INDEX A, B, C   R[A][R[B]] = R[C]
    LEN = 0x64,             // LEN A, B            R[A] = len(R[B])
    LIST_APPEND = 0x65,     // LIST_APPEND A, B    R[A].append(R[B])
    DICT_SET = 0x66,        // DICT_SET A, B, C    R[A][R[B]] = R[C]

    // 字符串操作
    STR_CAT = 0x70,         // STR_CAT A, B, C     R[A] = str(R[B]) + str(R[C])

    // 调试指令
    BREAKPOINT = 0x80,      // BREAKPOINT          触发断点
    DBG_LINE = 0x81,        // DBG_LINE Bx         行号标记

    // 内置函数
    ECHO = 0x90,            // ECHO A, B           echo R[A..A+B-1]

    // 控制指令
    HALT = 0xFF             // HALT                停止执行
};

/**
 * 指令结构体
 */
struct Instruction {
private:
    uint32_t data;

public:
    // 构造函数
    Instruction() : data(0) {}
    explicit Instruction(uint32_t raw) : data(raw) {}
    
    // ABC格式构造
    Instruction(OpCode op, uint8_t a = 0, uint8_t b = 0, uint8_t c = 0)
        : data((static_cast<uint32_t>(op) << 24) | 
               (static_cast<uint32_t>(a) << 16) | 
               (static_cast<uint32_t>(b) << 8) | 
               static_cast<uint32_t>(c)) {}
    
    // ABx格式构造
    Instruction(OpCode op, uint8_t a, uint16_t bx)
        : data((static_cast<uint32_t>(op) << 24) | 
               (static_cast<uint32_t>(a) << 16) | 
               static_cast<uint32_t>(bx)) {}

    // 字段提取
    OpCode opcode() const { return static_cast<OpCode>((data >> 24) & 0xFF); }
    uint8_t a() const { return (data >> 16) & 0xFF; }
    uint8_t b() const { return (data >> 8) & 0xFF; }
    uint8_t c() const { return data & 0xFF; }
    uint16_t bx() const { return data & 0xFFFF; }
    int16_t sbx() const { return static_cast<int16_t>(bx()) - 32767; }

    // 原始数据访问
    uint32_t raw() const { return data; }
    void set_raw(uint32_t raw) { data = raw; }

    // 字符串表示
    std::string to_string() const;
    
    // 调试输出
    std::string debug_string() const;
};

/**
 * 字节码程序
 */
class Bytecode {
private:
    std::vector<Instruction> instructions;
    std::vector<Value> constants;
    std::vector<std::string> names;
    std::vector<int> line_numbers;
    std::string source_file;
    
    // 调试信息支持（优化项1：Bytecode携带调试信息）
    std::shared_ptr<DebugInfo> debug_info_;
    
public:
    Bytecode() = default;
    explicit Bytecode(const std::string& filename) : source_file(filename) {}

    // 指令操作
    void add_instruction(const Instruction& inst);
    void add_instruction(OpCode op, uint8_t a = 0, uint8_t b = 0, uint8_t c = 0);
    void add_instruction(OpCode op, uint8_t a, uint16_t bx);
    
    size_t instruction_count() const { return instructions.size(); }
    const Instruction& get_instruction(size_t index) const;
    void set_instruction(size_t index, const Instruction& inst);

    // 常量池操作
    size_t add_constant(const Value& value);
    const Value& get_constant(size_t index) const;
    size_t constant_count() const;

    // 名字池操作
    size_t add_name(const std::string& name);
    const std::string& get_name(size_t index) const;
    size_t name_count() const { return names.size(); }

    // 行号映射
    void add_line_number(int line);
    int get_line_number(size_t pc) const;
    void set_source_file(const std::string& filename) { source_file = filename; }
    const std::string& get_source_file() const { return source_file; }

    // 调试输出
    std::string disassemble() const;
    void dump() const;

    // 清空
    void clear();

    // 访问器（用于VM执行）
    const std::vector<Instruction>& get_instructions() const { return instructions; }
    const std::vector<std::string>& get_names() const { return names; }
    
    // 常量访问器
    const std::vector<Value>& get_constants() const { return constants; }
    
    // 调试信息访问（优化项1新增）
    void set_debug_info(std::shared_ptr<DebugInfo> info) { debug_info_ = info; }
    std::shared_ptr<DebugInfo> get_debug_info() const { return debug_info_; }
    bool has_debug_info() const { return debug_info_ != nullptr; }
    
    // 自动创建并初始化调试信息
    std::shared_ptr<DebugInfo> ensure_debug_info();
};

/**
 * 指令构建辅助函数
 */
namespace instructions {
    // 数据移动
    inline Instruction load_const(uint8_t reg, uint16_t const_idx) {
        return Instruction(OpCode::LOAD_CONST, reg, const_idx);
    }
    
    inline Instruction load_nil(uint8_t reg) {
        return Instruction(OpCode::LOAD_NIL, reg);
    }
    
    inline Instruction load_true(uint8_t reg) {
        return Instruction(OpCode::LOAD_TRUE, reg);
    }
    
    inline Instruction load_false(uint8_t reg) {
        return Instruction(OpCode::LOAD_FALSE, reg);
    }
    
    inline Instruction move(uint8_t dst, uint8_t src) {
        return Instruction(OpCode::MOVE, dst, src);
    }

    // 变量操作
    inline Instruction load_global(uint8_t reg, uint16_t name_idx) {
        return Instruction(OpCode::LOAD_GLOBAL, reg, name_idx);
    }
    
    inline Instruction store_global(uint8_t reg, uint16_t name_idx) {
        return Instruction(OpCode::STORE_GLOBAL, reg, name_idx);
    }
    
    inline Instruction load_local(uint8_t dst, uint8_t src) {
        return Instruction(OpCode::LOAD_LOCAL, dst, src);
    }
    
    inline Instruction store_local(uint8_t dst, uint8_t src) {
        return Instruction(OpCode::STORE_LOCAL, dst, src);
    }
    
    // 作用域操作
    inline Instruction load_scope(uint8_t reg, uint8_t scope_id, uint16_t name_idx) {
        // 格式: | OpCode(8) | A(8) | ScopeId(4) | Reserved(4) | NameIdx(12) |
        uint16_t bx = (static_cast<uint16_t>(scope_id & 0xF) << 12) | (name_idx & 0xFFF);
        return Instruction(OpCode::LOAD_SCOPE, reg, bx);
    }
    
    inline Instruction store_scope(uint8_t scope_id, uint16_t name_idx, uint8_t value_reg) {
        // 格式: | OpCode(8) | ValueReg(8) | ScopeId(4) | Reserved(4) | NameIdx(12) |
        uint16_t bx = (static_cast<uint16_t>(scope_id & 0xF) << 12) | (name_idx & 0xFFF);
        return Instruction(OpCode::STORE_SCOPE, value_reg, bx);
    }

    // 算术运算
    inline Instruction add(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::ADD, dst, lhs, rhs);
    }
    
    inline Instruction sub(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::SUB, dst, lhs, rhs);
    }
    
    inline Instruction mul(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::MUL, dst, lhs, rhs);
    }
    
    inline Instruction div(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::DIV, dst, lhs, rhs);
    }
    
    inline Instruction mod(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::MOD, dst, lhs, rhs);
    }
    
    inline Instruction neg(uint8_t dst, uint8_t src) {
        return Instruction(OpCode::NEG, dst, src);
    }

    // 比较运算
    inline Instruction eq(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::EQ, dst, lhs, rhs);
    }
    
    inline Instruction ne(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::NE, dst, lhs, rhs);
    }
    
    inline Instruction lt(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::LT, dst, lhs, rhs);
    }
    
    inline Instruction le(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::LE, dst, lhs, rhs);
    }
    
    inline Instruction gt(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::GT, dst, lhs, rhs);
    }
    
    inline Instruction ge(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::GE, dst, lhs, rhs);
    }

    // 逻辑运算
    inline Instruction and_op(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::AND, dst, lhs, rhs);
    }
    
    inline Instruction or_op(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::OR, dst, lhs, rhs);
    }
    
    inline Instruction not_op(uint8_t dst, uint8_t src) {
        return Instruction(OpCode::NOT, dst, src);
    }

    // 控制流
    inline Instruction jmp(int16_t offset) {
        return Instruction(OpCode::JMP, 0, static_cast<uint16_t>(offset + 32767));
    }
    
    inline Instruction jmp_if_true(uint8_t reg, int16_t offset) {
        return Instruction(OpCode::JMP_IF_TRUE, reg, static_cast<uint16_t>(offset + 32767));
    }
    
    inline Instruction jmp_if_false(uint8_t reg, int16_t offset) {
        return Instruction(OpCode::JMP_IF_FALSE, reg, static_cast<uint16_t>(offset + 32767));
    }
    
    // 迭代指令
    inline Instruction iter_init(uint8_t iter_reg, uint8_t obj_reg) {
        return Instruction(OpCode::ITER_INIT, iter_reg, obj_reg);
    }
    
    inline Instruction iter_next(uint8_t iter_reg, int16_t loop_offset) {
        return Instruction(OpCode::ITER_NEXT, iter_reg, static_cast<uint16_t>(loop_offset + 32767));
    }

    // 函数调用
    inline Instruction call(uint8_t result, uint8_t func, uint8_t argc) {
        return Instruction(OpCode::CALL, result, func, argc);
    }
    
    inline Instruction return_op(uint8_t start, uint8_t count) {
        return Instruction(OpCode::RETURN_OP, start, count);
    }
    
    inline Instruction func_def(uint8_t func_idx, uint16_t skip_offset) {
        return Instruction(OpCode::FUNC_DEF, func_idx, skip_offset);
    }

    // 数据结构
    inline Instruction new_list(uint8_t reg, uint8_t capacity = 0) {
        return Instruction(OpCode::NEW_LIST, reg, capacity);
    }
    
    inline Instruction new_dict(uint8_t reg) {
        return Instruction(OpCode::NEW_DICT, reg);
    }
    
    inline Instruction get_index(uint8_t dst, uint8_t obj, uint8_t key) {
        return Instruction(OpCode::GET_INDEX, dst, obj, key);
    }
    
    inline Instruction set_index(uint8_t obj, uint8_t key, uint8_t value) {
        return Instruction(OpCode::SET_INDEX, obj, key, value);
    }
    
    inline Instruction len(uint8_t dst, uint8_t obj) {
        return Instruction(OpCode::LEN, dst, obj);
    }
    
    inline Instruction list_append(uint8_t list, uint8_t value) {
        return Instruction(OpCode::LIST_APPEND, list, value);
    }
    
    inline Instruction dict_set(uint8_t dict, uint8_t key, uint8_t value) {
        return Instruction(OpCode::DICT_SET, dict, key, value);
    }

    // 字符串操作
    inline Instruction str_cat(uint8_t dst, uint8_t lhs, uint8_t rhs) {
        return Instruction(OpCode::STR_CAT, dst, lhs, rhs);
    }

    // 调试
    inline Instruction breakpoint() {
        return Instruction(OpCode::BREAKPOINT);
    }
    
    inline Instruction dbg_line(uint16_t line) {
        return Instruction(OpCode::DBG_LINE, 0, line);
    }

    // 内置函数
    inline Instruction echo(uint8_t start, uint8_t count) {
        return Instruction(OpCode::ECHO, start, count);
    }

    // 控制
    inline Instruction halt() {
        return Instruction(OpCode::HALT);
    }
}

} // namespace viml
